/*
    File:       Spectrum.h

    Function:	Provides classes for manipulating spectra

    Author:     Andrew Willmott

    Copyright:  (c) 1999-2000, Andrew Willmott
*/

#pragma once

#include "Geometry.h"
#include "Image.h"

class Spectrum : public Vecf
{
public:
	
				Spectrum() : Vecf(kComponents)
				{ MakeZero(); };
				Spectrum(const Vecf &v) : Vecf(v)
				{ Assert(Elts() == kComponents, "bad spectrum"); };
				Spectrum(Float k) : Vecf(kComponents)
				{ MakeBlock(k); };

	Colour		ToCIE_XYZ();

	static Int	GetNumComponents()
				{ return(kComponents); };

	static const Int	kComponents;	// number of (constant) basis functions
	static const Float	kStart;			// start of spectrum
	static const Float	kEnd;			// end of spectrum
};

class SpectralCurve
{
public:
	virtual			~SpectralCurve();
	
					operator Spectrum();

	virtual Float	Sample(Float lambda) const = 0;
					// sample curve at wavelength lambda
	virtual Float	Integral(Float lambda) const;
					// return integral of curve from 0 to lambda
	virtual Float	MaxCmpt() const;

	Void			MakeImage(Image &image, ClrReal maxAmplitude = -1.0);
					// Plot the spectrum into image.
	Colour			ToCIE_XYZ();
					// map the spectrum to the CIE XYZ colour system
};

class RegularSpectralCurve : public SpectralCurve
{
public:
				RegularSpectralCurve(Float *sdata, Int start, Int end, Int divisions);
				~RegularSpectralCurve();

	Float		Sample(Float lambda) const;
//	Float		Integral(Float lambda) const;

protected:
	Float		*data;
	Float		*accumData;
	Int			waveDivs;
	Float		waveStart, waveEnd, waveDelta;
};

class IrregularSpectralCurve : public SpectralCurve
{
public:
				IrregularSpectralCurve();
				IrregularSpectralCurve(Float *amps, Float *wavs, Int divs);
				~IrregularSpectralCurve();

	Float		Sample(Float lambda) const;
//	Float		Integral(Float lambda) const;

	IrregularSpectralCurve
				&ReadSDFile(FileName filename);

protected:
	Float		*amplitudes;
	Float		*accumAmplitudes;
	Float		*wavelengths;
	Int			divisions;
};

// --- CIE colour matching functions ------------------------------------

extern RegularSpectralCurve kCIE_xbar;
extern RegularSpectralCurve kCIE_ybar;
extern RegularSpectralCurve kCIE_zbar;

// --- useful utilities --------------------------------------------------

Colour 		WavelengthToXYZ(ClrReal lambda);

class ChromaticitySpectrum : public SpectralCurve
{
public:
	ChromaticitySpectrum(ClrReal x, ClrReal y);

	Float		Sample(Float lambda) const;

protected:
	ClrReal		M1, M2;
};

class BlackBodySpectrum : public SpectralCurve
{
public:
	BlackBodySpectrum(Float temperature);

	Float		Sample(Float lambda) const;

protected:
	Float		temp;
};

Void DrawChromaticityImage(Image &image);

#endif
